package com.ecarx.library_base.scoket.callback;

import android.os.Handler;
import android.os.HandlerThread;
import android.os.Process;

import com.ecarx.library_base.scoket.Singleton;
import com.ecarx.library_base.scoket.SocketManager;

import java.util.Calendar;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author WL on 2023/04/18
 */
public final class ListenerQueue {
    private volatile boolean mStopFlag = false;
    private volatile boolean mHasTask = false;

    //callback 队列
    private final Map<Long, Packetlistener> mCallBackQueue = new ConcurrentHashMap<>();
    private final Handler timerHandler;

    private static final Singleton<HandlerThread> gSocketManager = new Singleton<HandlerThread>() {
        @Override
        protected HandlerThread create() {
            HandlerThread handlerThread = new HandlerThread("ListenerQueue", Process.THREAD_PRIORITY_DEFAULT);
            handlerThread.start();
            return handlerThread;
        }
    };

    public ListenerQueue() {
        timerHandler = new Handler(gSocketManager.get().getLooper());
    }

    public void onStart() {
        mStopFlag = false;
        startTimer();
    }

    public void onDestroy() {
        mCallBackQueue.clear();
        stopTimer();
    }

    //以前是TimerTask处理方式
    private void startTimer() {
        if (!mStopFlag && !mHasTask) {
            mHasTask = true;
            timerHandler.postDelayed(() -> {
                timerImpl();
                mHasTask = false;
                startTimer();
            }, 5 * 1000);
        }
    }

    private void stopTimer() {
        mStopFlag = true;
    }

    private void timerImpl() {
        long currentRealtime = Calendar.getInstance().getTimeInMillis();

        for (java.util.Map.Entry<Long, Packetlistener> entry : mCallBackQueue.entrySet()) {

            Packetlistener packetlistener = entry.getValue();
            Long seqNo = entry.getKey();
            long timeRange = currentRealtime - packetlistener.getCreateTime();

            try {
                if (timeRange >= packetlistener.getTimeOut()) {
                    Packetlistener listener = pop(seqNo);
                    if (listener != null) {
                        listener.onTimeout();
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    public void push(long seqNo, Packetlistener packetlistener) {
        if (seqNo <= 0 || null == packetlistener) {
            return;
        }
        mCallBackQueue.put(seqNo, packetlistener);
    }


    public Packetlistener pop(long seqNo) {
        if (mCallBackQueue.containsKey(seqNo)) {
            return mCallBackQueue.remove(seqNo);
        }
        return null;
    }
}
